package xinyu.customer.web;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import androidx.appcompat.app.AlertDialog;

import com.logos.tool.DialogHelper;


/**
 * 功能描述: 浏览器,视频、图片都支持
 * <p>
 * 作者: July
 * 日期: 2018/9/23 下午10:50
 */
public class XinYangWebView extends WebView {

    private OnFinishListener mOnFinishFinish;
    private OnLoadedHtmlListener mHTMLListener;
    private OnImageClickListener mImageClickListener;
    private OnVideoClickListener mVideoClickListener;
    private boolean isFinish;
    private WebRule mWebRule;
    private boolean isRemove;

    public XinYangWebView(Context context) {
        this(context, null);
    }

    public XinYangWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initWebView();
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void initWebView() {
        // webview从5.0开始默认不允许混合模式,https中不能加载http资源,需要设置开启。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            getSettings().setSafeBrowsingEnabled(false);
        }

        // 开启DOM storage API 功能
        getSettings().setDomStorageEnabled(true);
        // 如果访问的页面中要与Javascript交互，则webview必须设置支持Javascript
        getSettings().setJavaScriptEnabled(true);
        // 支持通过JS打开新窗口
        getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

        // 添加JS脚本监听
        addJavascriptInterface(new JavascriptInterface(), "mark");

        setWebChromeClient(new WebChromeClient() {
            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
                if (mOnFinishFinish != null) {
                    mOnFinishFinish.onReceivedTitle(title);
                }
            }

            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                Log.d("WebView", "onJsAlert => url: " + url + " message: " + message);
                final AlertDialog.Builder builder = DialogHelper.getMessageDialog(view.getContext(), message);
                // 禁止响应按back键的事件
                builder.setCancelable(false);
                AlertDialog dialog = builder.create();
                dialog.show();
                result.confirm(); // 因为没有绑定事件，需要强行confirm,否则页面会变黑显示不了内容。
                return true;
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                Log.d("WebView", "onJsConfirm => url: " + url + " message: " + message);
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                Log.d("WebView", "onJsPrompt => url: " + url + " message: " + message);
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }

            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                if (!isRemove) {
                    isRemove = true;
                    startLoadRule();
                }
                if (mOnFinishFinish != null) {
                    mOnFinishFinish.onProgressChange(newProgress);
                }
            }
        });

        setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return super.shouldOverrideUrlLoading(view, request);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    exeExpandRule();
                }
                postDelayed(() -> isFinish = true, 2000);
                if (mOnFinishFinish != null) {
                    mOnFinishFinish.onFinish();
                }
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);
                if (mOnFinishFinish != null) {
                    mOnFinishFinish.onError();
                }
            }

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
                return super.shouldInterceptRequest(view, request);
            }
        });

        // 内容长安监听
        setOnLongClickListener(v -> {
            XinYangWebView webView = (XinYangWebView) v;
            HitTestResult result = webView.getHitTestResult();
            if (null == result) {
                return false;
            }

            int type = result.getType();
            if (type == HitTestResult.UNKNOWN_TYPE) {
                return false;
            }
            if (type == HitTestResult.EDIT_TEXT_TYPE) {
                // let TextViewhandles context menu
                return false;
            }

            // Setup custom handlingdepending on the type
            switch (type) {
                case HitTestResult.PHONE_TYPE:
                    // 处理拨号
                    break;
                case HitTestResult.EMAIL_TYPE:
                    // 处理Email
                    break;
                case HitTestResult.GEO_TYPE:
                    break;
                case HitTestResult.SRC_ANCHOR_TYPE:
                    // 超链接
                    break;
                case HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
                case HitTestResult.IMAGE_TYPE:
                    // 处理长按图片的菜单项
                    break;
                default:
                    break;
            }
            return false;
        });
    }

    public void setUserAgent(String ua) {
        getSettings().setUserAgentString(ua);
    }

    /**
     * 启用缩放功能
     */
    public void enableZoom() {
        WebSettings settings = getSettings();
        // 缩放处理
        settings.setUseWideViewPort(true);         // 将图片调整到适合webview的大小
        settings.setLoadWithOverviewMode(true);    // 缩放至屏幕的大小
        settings.setSupportZoom(true);             // 支持缩放，默认为true。是下面那个的前提。
        settings.setBuiltInZoomControls(true);     // 设置内置的缩放控件。 这个取决于setSupportZoom(), 若setSupportZoom(false)，则该WebView不可缩放，这个不管设置什么都不能缩放。
        settings.setDisplayZoomControls(false);    // 隐藏原生的缩放控件

        // 内容布局
        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); // 支持内容重新布局
        settings.supportMultipleWindows(); // 多窗口
    }

    /**
     * 文件缓存
     * <p>
     * LOAD_CACHE_ELSE_NETWORK  优先使用缓存
     * LOAD_CACHE_ONLY          只在缓存中读取
     * LOAD_NO_CACHE            不使用缓存
     */
    public void enableCache() {
//        WebSettings settings = getSettings();
        // 文件缓存
//        settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        //settings.setAllowFileAccess(true); // 设置可以访问文件

        // 其他设置
        //settings.setNeedInitialFocus(true);             // 当webview调用requestFocus时为webview设置节点
        //settings.setLoadsImagesAutomatically(true);     // 支持自动加载图片
        //settings.setDefaultTextEncodingName("utf-8");   // 设置编码格式
        //settings.setPluginState(WebSettings.PluginState.OFF); // 设置是否支持flash插件
        //settings.setDefaultFontSize(20); // 设置默认字体大小
    }

    /**
     * 去除广告规则
     */
    private void exeRemoveRule() {
        if (mWebRule == null) return;
        String[] rules = mWebRule.getRemoveRules();
        if (rules == null || rules.length == 0) return;
        for (String rule : rules) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                evaluateJavascript(rule, null);
            }
        }
    }

    /**
     * 展开全文规则
     */
    private void exeExpandRule() {
        if (mWebRule == null) return;
        String[] rules = mWebRule.getExpandRules();
        if (rules == null || rules.length == 0) return;
        for (String rule : rules) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                evaluateJavascript(rule, null);
            }
        }
    }

    private int delay = 1;

    public void setWebRule(WebRule mWebRule) {
        this.mWebRule = mWebRule;
    }

    private void startLoadRule() {
        if (Build.VERSION.SDK_INT <= 22) {
            delay = 50;
        } else {
            delay = 20;
        }

        if (mWebRule == null || mWebRule.getRemoveRules() == null || mWebRule.getRemoveRules().length == 0) {
            return;
        }

        postDelayed(new Runnable() {
            @Override
            public void run() {
                if (isFinish) {
                    return;
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    exeRemoveRule();
                }
                if (!isFinish) {
                    postDelayed(this, delay);
                }
            }
        }, 0);
    }

    public void onDestroy() {
        isFinish = true;
        ViewParent parent = getParent();
        if (parent != null) {
            ((ViewGroup) parent).removeView(this);
        }
        stopLoading();
        getSettings().setJavaScriptEnabled(false);
        clearHistory();
        clearView();
        removeAllViews();
        mOnFinishFinish = null;
        mImageClickListener = null;
        mVideoClickListener = null;
        destroy();
    }

    public boolean hasRule() {
        return mWebRule != null;
    }

    public void getHtml(OnLoadedHtmlListener listener) {
        this.mHTMLListener = listener;
        loadUrl("javascript:window.mark.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
    }

    private void addJavaScript() {
        loadUrl("javascript:(function(){" +
                "var objs = document.getElementsByTagName(\"img\"); " +
                "for(var i=0;i<objs.length;i++)  " +
                "{"
                + "    objs[i].onclick=function()  " +
                "    {  "
                + "        window.mark.openImage(this.src);  " +
                "    }  " +
                "}" +
                "})()");

        loadUrl("javascript:(function(){" +
                "var objs = document.getElementsByTagName(\"video\"); " +
                "for(var i=0;i<objs.length;i++)  " +
                "{"
                + "    objs[i].onclick=function()  " +
                "    {  "
                + "        window.mark.openVideo(this.src);  " +
                "    }  " +
                "}" +
                "})()");
    }

    public void setOnImageClickListener(OnImageClickListener listener) {
        this.mImageClickListener = listener;
    }

    public void setOnVideoClickListener(OnVideoClickListener listener) {
        this.mVideoClickListener = listener;
    }

    public void setOnFinishFinish(OnFinishListener listener) {
        this.mOnFinishFinish = listener;
    }

    private class JavascriptInterface {

        @android.webkit.JavascriptInterface
        public void openImage(String img) {
            if (mImageClickListener != null) {
                mImageClickListener.onClick(img);
            }
        }

        @android.webkit.JavascriptInterface
        public void openVideo(String img) {
            if (mVideoClickListener != null) {
                mVideoClickListener.onClick(img);
            }
        }

        @android.webkit.JavascriptInterface
        public void showHtml(String html) {
            if (mHTMLListener != null) {
                mHTMLListener.showHtml(html);
            }
        }
    }

    public interface OnLoadedHtmlListener {

        void showHtml(String html);
    }


    public interface OnImageClickListener {

        void onClick(String url);
    }

    public interface OnVideoClickListener {

        void onClick(String url);
    }

    public interface OnFinishListener {

        void onReceivedTitle(String title);

        void onProgressChange(int progress);

        void onError();

        void onFinish();
    }
}
